package nl.saxion.act.bus;

import java.util.List;

import nl.saxion.act.gameframework.Actor;
import nl.saxion.act.gameframework.LevelGenerator;
import nl.saxion.act.gameframework.World;
import nl.saxion.act.logging.Assert;

public class BuswereldLevelGenerator extends LevelGenerator {
	BuschauffeurFactoryInterface factory;
	public BuswereldLevelGenerator( BuschauffeurFactoryInterface buschauffeurFactory ) {
		factory = buschauffeurFactory;
	}
	
	public void createNextLevel( World world ) {
		Buswereld buswereld             = (Buswereld) world;
		int       level                 = buswereld.getLevel() % 10;
		int maxAantalPassagiersPerHalte = level < 4 ? level * 2 : level + 3 ;
		
		if ( buswereld.getNrOfPassiveActors() == 0 ) {
			buswereld.clear();
			buswereld.readRoute();
		} else {
			verwijderReizigersBijHalteEnGenereerNieuwe( world, maxAantalPassagiersPerHalte );
		}
		verwijderOudeBusEnGenereerNieuwe(buswereld);
		buswereld.resetLastTime();
	}

	int aantalPassagiers;
	private void verwijderReizigersBijHalteEnGenereerNieuwe(World world, int maxAantalPassagiersPerHalte) {
		List<Actor> haltes = world.getAllActorsOfType( HalteProxy.class );
		Assert.check( haltes.size() > 1, "haltelijst bevat minder dan twee haltes (" + haltes.size() + ")" );
		
		aantalPassagiers = 0;
		for ( Actor actor : haltes ) {
			HalteProxy halte = (HalteProxy) actor;
			verwijderAlleReizigersBijHalte( halte );

			int aantalReizigersBijHalte = (int) ( Math.random() * maxAantalPassagiersPerHalte );				
			maakAantalReizigersEnVoegToeAanHalte( haltes, halte, aantalReizigersBijHalte );
		}
	}

	private void maakAantalReizigersEnVoegToeAanHalte( List<Actor> haltes, HalteProxy halte, int aantalReizigers ) {
		while ( aantalReizigers-- > 0 ) {
			String naam = "reiziger " + ++aantalPassagiers;
			HalteProxy andereHalte;
			do {
				andereHalte = (HalteProxy) haltes.get( (int) ( Math.random() * haltes.size() ) );
			} while ( halte.equals( andereHalte ) );
			
			halte.add( new Reiziger( naam, andereHalte.getNaam() ) );
		}
	}

	private void verwijderAlleReizigersBijHalte( HalteProxy halte ) {
		for ( Reiziger reiziger : halte.getReizigers() )
			halte.remove( reiziger );
	}

	private void verwijderOudeBusEnGenereerNieuwe( Buswereld busWorld ) {
		for ( Actor actor : busWorld.getAllActiveActorsOfType( BusActor.class ) ) {
			busWorld.removeActor( actor );
		}

		AbstracteBuschauffeur buschauffeur = factory.getBuschauffeur( busWorld.getLevel() );
		BusActor busActor = new BusActor( 0, 0, busWorld, new Bus( 155, 3, 0, 0, busWorld ), buschauffeur );
		busWorld.addActor( busActor );

		creeerInitieleBustoestand( buschauffeur );
		busActor.setRoute( busWorld.getRoute() );
	}

	private void creeerInitieleBustoestand( AbstracteBuschauffeur buschauffeur ) {
		komTotStilstandIndienNodigEnSluitDeurIndienNodig( buschauffeur );
		buschauffeur.startBusmotor();
		buschauffeur.accelereerEnGaRijden();
	}

	private void komTotStilstandIndienNodigEnSluitDeurIndienNodig( AbstracteBuschauffeur buschauffeur ) {
		if ( buschauffeur.getBussnelheid() > 0  ) buschauffeur.deaccelereerTotStilstand();
		if ( buschauffeur.isBusGestart()        ) buschauffeur.stopBusmotor();
		if ( buschauffeur.isBusdeurOpen()       ) buschauffeur.sluitBusdeur();
	}
}
